#pragma once

#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

using namespace EpollerModule;
using Connection_t = std::shared_ptr<Connection>;

class Reactor
{
	static const int _revs_num = 64;
	bool IsConnectionExists(int sockfd)
	{
		return _connections.find(sockfd) != _connections.end();
	}

public:
	Reactor() : _running(false), _epoller(std::make_unique<EpollerModule::Epoller>())
	{
		_epoller->Create();
	}
	~Reactor()
	{
	}
    // 插入连接
	void insertConnection(Connection_t conn)
	{
		auto iter = _connections.find(conn->Sockfd());
		if (iter == _connections.end())
		{
			// 说明该链接为新链接，进行插入
			_connections[conn->Sockfd()] = conn;
			// 2. 把新插入进来的连接，写透到内核的epoll中
			_epoller->ADD(conn->Sockfd(), conn->GetEvents());
			// 3. 设置关联关系，让connection回指当前对象
			conn->SetOwner(this);
			LOG(LogLevel::DEBUG) << "add connection success: " << conn->Sockfd();
		}
	}
	// 修改连接的读写事件
	void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        if (IsConnectionExists(sockfd))
        {
            // 修改用户层connection的事件
            uint32_t events = ((readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET);
            _connections[sockfd]->Setevents(events);
            // 写透到内核中
            _epoller->Mod(sockfd, _connections[sockfd]->GetEvents());
        }
    }
	// 删除连接
    void DelConnection(int sockfd)
    {
        if (IsConnectionExists(sockfd))
        {
            // 1. 从内核中异常对sockfd的关心
            _epoller->Del(sockfd);
            // 2. 关闭特定的文件描述
            _connections[sockfd]->Close();
            // 3. 从_connections中移除对应的connection
            _connections.erase(sockfd);
        }
    }
	// 派发
	void Dispatcher(int num)
	{
		for (int i = 0; i < num; i++)
		{
			// 开始进行派发, 派发给指定的模块
			int sockfd = _revs[i].data.fd;
			uint32_t event = _revs[i].events;
			// 异常事件，转换成为读写事件
			if (event & EPOLLHUP || event & EPOLLERR)
			{
				event = EPOLLIN | EPOLLOUT;
			}
			if (event & EPOLLIN && IsConnectionExists(sockfd))
			{
				// 读事件，处理读事件
				_connections[sockfd]->Recver();
			}
			if (event & EPOLLOUT && IsConnectionExists(sockfd))
			{
				// 写事件，处理写事件
				_connections[sockfd]->Sender();
			}
		}
	}
	// 循环
	void LoopOnce(int timeout)
	{
		int num = _epoller->Wait(_revs, _revs_num, timeout);
		Dispatcher(num);
	}
	void DebugPrint()
	{
		std::cout << "Epoller 管理的fd: ";
		for (auto &iter : _connections)
		{
			std::cout << iter.first << " ";
		}
		std::cout << std::endl;
	}
	void Loop()
	{
		_running = true;
		int timeout = -1;
		while (true)
		{
			LoopOnce(timeout);
			DebugPrint();
		}
		_running = false;
	}
	void Stop()
	{
		_running = false;
	}

private:
	bool _running;
	std::unique_ptr<EpollerModule::Epoller> _epoller;
	std::unordered_map<int, Connection_t> _connections;
	struct epoll_event _revs[_revs_num];
};